<cfcomponent>
	<cfset VARIABLES.LDAP_Host = "10.100.1.101" />
	<cfset VARIABLES.LDAP_User = "SCF\Userlist" />
	<cfset VARIABLES.LDAP_Pass = "DefinedMan" />
	<cfset VARIABLES.LDAP_Start = "dc=SouthcentralFoundation,dc=com" />


	<!--- Gets all the users in active directory, returning their DN and
		sAMAccountName. Useful for caching --->
	<cffunction access="public" name="getAllUsers" returntype="query">
		<cfldap action="QUERY" name="ldapUser" server="#LDAP_Host#"
			start="ou=SCFUsers,#LDAP_Start#"
			username="#LDAP_User#" password="#LDAP_Pass#"
			attributes="distinguishedName,sAMAccountName,title,physicalDeliveryOfficeName,department,manager,displayName,givenName,initials,sn,directReports,memberOf,userAccountControl" scope="SUBTREE"
			filter="(&(objectClass=user))"/>

		<cfreturn ldapUser />
	</cffunction>
    
    
    <!--- Gets all the groups in active directory, returning their DN and sAMAccountName. Useful for caching --->
    <cffunction access="public" name="getAllGroups" returntype="query">
        <cfldap action="QUERY" name="ldapUser" server="#LDAP_Host#"
            start="ou=SCFUsers,#LDAP_Start#"
            username="#LDAP_User#" password="#LDAP_Pass#"
            attributes="distinguishedName,sAMAccountName,groupType,managedBy,member" scope="SUBTREE"
            filter="(&(objectClass=group))"/>

        <cfreturn ldapUser />
    </cffunction>


	<!--- Returns a user's account name if a DN is provided --->
	<cffunction access="public" name="getAccountNameByDN" returntype="String">
		<cfargument name="DN" required="true" type="String" />

		<cftry>
		<cfldap action="QUERY" name="ldapUser" server="#LDAP_Host#"
			start="#ARGUMENTS.DN#"
			username="#LDAP_User#" password="#LDAP_Pass#"
			attributes="sAMAccountName" scope="SUBTREE"
			filter="(objectClass=user)"/>

			<cfreturn ldapUser.sAMAccountName />
			<cfcatch type="any">
				<cfreturn "" />
			</cfcatch>
		</cftry>
	</cffunction>
    
    
    <!--- Returns a group's name if a DN is provided --->
    <cffunction access="public" name="getGroupNameByDN" returntype="String">
        <cfargument name="DN" required="true" type="String" />

        <cftry>
        <cfldap action="QUERY" name="ldapUser" server="#LDAP_Host#"
            start="#ARGUMENTS.DN#"
            username="#LDAP_User#" password="#LDAP_Pass#"
            attributes="sAMAccountName" scope="SUBTREE"
            filter="(objectClass=group)"/>

            <cfreturn ldapUser.sAMAccountName />
            <cfcatch type="any">
                <cfreturn "" />
            </cfcatch>
        </cftry>
    </cffunction>


	<!--- Returns a group's DN if a displayName is provided --->
	<cffunction access="public" name="getGroupDNByDisplayName" returntype="String">
		<cfargument name="GroupName" required="true" type="String" />

		<cfldap action="QUERY" name="ldapGroup" server="#LDAP_Host#"
			start="ou=SCFUsers,#LDAP_Start#" username="#LDAP_User#" password="#LDAP_Pass#"
			attributes="distinguishedName" scope="SUBTREE"
			filter="(&(objectClass=group)(displayName=#ARGUMENTS.GroupName#))"/>
		<cfreturn ldapGroup.distinguishedName />
	</cffunction>


	<!--- Returns a user's DN if an accountName is provided --->
	<cffunction access="public" name="getUserDNByAccountName" returntype="String">
		<cfargument name="AccountName" required="true" type="String" />

		<cfldap action="QUERY" name="ldapUser" server="#LDAP_Host#"
			start="ou=SCFUsers,#LDAP_Start#"
			username="#LDAP_User#" password="#LDAP_Pass#"
			attributes="distinguishedName" scope="SUBTREE" separator="|"
			filter="(&(objectClass=user)(sAMAccountName=#ARGUMENTS.AccountName#))"/>

		<cfreturn ldapUser.distinguishedName />
	</cffunction>


	<!--- Adds a user (specified by DN) to a group (specified by DN) --->
	<cffunction access="public" name="addUserToGroup" returntype="String">
		<cfargument name="UserDN" required="true" type="String" />
		<cfargument name="GroupDN" required="true" type="String" />
		<cftry>
			<cfldap action="modify" dn="#ARGUMENTS.GroupDN#"
				attributes="member=#ARGUMENTS.UserDN#"
				separator=";" modifytype="add"
				server="#LDAP_Host#"
				username="#LDAP_User#"
				password="#LDAP_Pass#" />
			<cfcatch type="any">
				<cfreturn cfcatch.message />
			</cfcatch>
		</cftry>

		<cfreturn "" />
	</cffunction>


	<!--- Removes a user (specified by DN) from a group (specified by DN) --->
	<cffunction access="public" name="removeUserFromGroup" returntype="String">
		<cfargument name="UserDN" required="true" type="String" />
		<cfargument name="GroupDN" required="true" type="String" />
		<cftry>
			<cfldap action="modify" dn="#ARGUMENTS.GroupDN#"
				attributes="member=#ARGUMENTS.UserDN#"
				separator=";" modifytype="delete"
				server="#LDAP_Host#"
				username="#LDAP_User#"
				password="#LDAP_Pass#" />
			<cfcatch type="any">
				<cfreturn cfcatch.message />
			</cfcatch>
		</cftry>

		<cfreturn "" />
	</cffunction>


	<!--- Removes all members from a group (specified by DN) --->
	<cffunction access="public" name="removeGroupMembers" returntype="String">
		<cfargument name="GroupDN" required="true" type="String" />
		<cftry>
			<cfldap action="modify" modifyType="delete"
				dn="#ARGUMENTS.GroupDN#" attributes="member"
				separator=";" server="#LDAP_Host#"
				username="#LDAP_User#" password="#LDAP_Pass#" />
			<cfcatch type="any">
				<cfreturn cfcatch.message />
			</cfcatch>
		</cftry>

		<cfreturn "" />
	</cffunction>


	<!--- Returns the DNs of the members of a group (specified by DisplayName)
		as an array --->
	<cffunction access="public" name="getGroupMembers" returntype="array">
		<cfargument name="GroupName" required="true" type="String" />

		<cfldap action="QUERY" name="ldapGroup" server="#LDAP_Host#"
			start="ou=SCFUsers,#LDAP_Start#" username="#LDAP_User#"
			password="#LDAP_Pass#" attributes="member" scope="SUBTREE"
			separator=";"
			filter="(&(objectClass=group)(sAMAccountName=#GroupName#))"/>

		<cfreturn ListToArray(ldapGroup.member, ";", false) />
	</cffunction>


	<!--- Returns all the groups (their displayName, members and the group's DN
		in the "Dynamic Groups" OU --->
	<cffunction access="public" name="getDynamicGroupMembers" returntype="query">
		<cfargument name="Separator" required="false" type="String" default=";" />

		<cfldap action="QUERY" name="ldapGroup" server="#LDAP_Host#"
			start="ou=Dynamic Groups,ou=SCFUsers,#LDAP_Start#" username="#LDAP_User#"
			password="#LDAP_Pass#" attributes="displayName,member,distinguishedName"
			scope="SUBTREE" separator="#ARGUMENTS.Separator#"
			filter="(objectClass=group)"/>

		<cfreturn ldapGroup />
	</cffunction>


	<!--- Given a DN, replaces specified attributes in that object --->
    <cffunction access="public" name="replaceAttributesByDN" returntype="String">
        <cfargument name="DN" required="true" type="String" />
        <cfargument name="Attributes" required="true" type="String" />
        <cfargument name="Separator" required="false" type="String" default=";" />

        <cftry>
            <cfldap action="modify" modifyType="replace"
                dn="#ARGUMENTS.DN#" attributes="#ARGUMENTS.Attributes#"
                separator="#ARGUMENTS.Separator#" server="#LDAP_Host#"
                username="#LDAP_User#" password="#LDAP_Pass#" />
            <cfcatch type="any">
                <cfreturn cfcatch.message />
            </cfcatch>
        </cftry>

        <cfreturn "" />
    </cffunction>


	<!--- Makes a do-nothing LDAP query using the specified credientals -
		effectively authenticates a username and password pair --->
	<cffunction access="public" name="authenticate" returntype="boolean">
		<cfargument name="Username" required="true" type="String" />
		<cfargument name="Password" required="true" type="String" />

		<cftry>
			<cfldap action="QUERY" name="ldapAuth" server="#LDAP_Host#"
				start="#LDAP_Start#" attributes="name" scope="base"
				username="#ARGUMENTS.Username#" password="#ARGUMENTS.Password#" />
			<cfcatch type="any">
				<cfreturn false />
			</cfcatch>
		</cftry>
		<cfreturn true />
	</cffunction>


	<!--- Executes a do-nothing LDAP query, using the default credientals -
		useful for determining the status of the AD server --->
	<cffunction access="public" name="isActiveDirectoryUp" returntype="boolean">
		<cftry>
			<cfldap action="QUERY" name="ldapAuth" server="#LDAP_Host#"
				start="#LDAP_Start#" attributes="name" scope="base"
				username="#LDAP_User#" password="#LDAP_Pass#" />
			<cfcatch type="any">
				<cfreturn false />
			</cfcatch>
		</cftry>
		<cfreturn true />
	</cffunction>


    <!--- Gets a query of user attributes by DN --->
    <cffunction access="public" name="getUserAttributesByDN" returntype="query">
        <cfargument name="DN" required="false" type="String" default="" />
        <cfargument name="Attributes" required="false" type="String"
            default="displayName,department,title,manager,member,distinguishedName,
            userAccountControl,homeDirectory,homeDrive,msExchHideFromAddressLists,
            givenName,initials,sn,userPrincipalName,sAMAccountName,whenChanged,physicalDeliveryOfficeName,
                memberOf,displayName,givenName,initials,sn,directReports,lastLogoff,lastLogon,logonCount" />

        <cfldap action="QUERY" name="ldapAttr" server="#LDAP_Host#"
            start="#ARGUMENTS.DN#" username="#LDAP_User#" password="#LDAP_Pass#"
            filter="(&(objectClass=*))" attributes="#ARGUMENTS.Attributes#" />

        <cfreturn ldapAttr />
    </cffunction>
    
    
    <!--- Gets a query of Gropup attributes by DN --->
    <cffunction access="public" name="getGroupAttributesByDN" returntype="query">
        <cfargument name="DN" required="false" type="String" default="" />
        <cfargument name="Attributes" required="false" type="String"
            default="displayName,member,distinguishedName" />

        <cfldap action="QUERY" name="ldapAttr" server="#LDAP_Host#"
            start="#ARGUMENTS.DN#" username="#LDAP_User#" password="#LDAP_Pass#"
            filter="(&(objectClass=group))" attributes="#ARGUMENTS.Attributes#" />

        <cfreturn ldapAttr />
    </cffunction>

</cfcomponent>